#include <stdio.h>
#include "array.h"

typedef struct student_array {
    char name[10];
    int age;
    int high;
} student_t;

// 必须是一个指针类型, 是因为StudentArray保存指针对象
// 也就是说
// StudentArray是一个指针数组，保存student_t的指针，保存的指针指向实际的元素对象
#if 1
ARRAY_DECL(student_t *, StudentArray)
#else
struct StudentArray {
    student_t** ptr;
    size_t size;
    size_t maxsize;
};
typedef struct StudentArray StudentArray;
static inline student_t** StudentArray_data(StudentArray* p) {
    return p->ptr;
}
static inline int StudentArray_size(StudentArray* p) {
    return p->size;
}
static inline int StudentArray_maxsize(StudentArray* p) {
    return p->maxsize;
}
static inline int StudentArray_empty(StudentArray* p) {
    return p->size == 0;
}
static inline student_t** StudentArray_at(StudentArray* p, int pos) {
    if (pos < 0) {
        pos += p->size;
    }
    ((pos >= 0 && pos < p->size) ? (void)(0)
                                 : __assert_fail("pos >= 0 && pos < p->size", "/data/hb/libhv/examples/array_test.c", 13, __extension__ __PRETTY_FUNCTION__));
    return p->ptr + pos;
}
static inline student_t** StudentArray_front(StudentArray* p) {
    return p->size == 0 ? ((void*)0) : p->ptr;
}
static inline student_t** StudentArray_back(StudentArray* p) {
    return p->size == 0 ? ((void*)0) : p->ptr + p->size - 1;
}
static inline void StudentArray_init(StudentArray* p, int maxsize) {
    p->size = 0;
    p->maxsize = maxsize;
    do {
        *(void**)&(p->ptr) = hv_zalloc(sizeof(student_t*) * maxsize);
        ;
    } while (0);
}
static inline void StudentArray_clear(StudentArray* p) {
    p->size = 0;
    memset(p->ptr, 0, sizeof(student_t*) * p->maxsize);
}
static inline void StudentArray_cleanup(StudentArray* p) {
    do {
        if (p->ptr) {
            hv_free(p->ptr);
            ;
            p->ptr = ((void*)0);
        }
    } while (0);
    p->size = p->maxsize = 0;
}
static inline void StudentArray_resize(StudentArray* p, int maxsize) {
    if (maxsize == 0) maxsize = 16;
    p->ptr = (student_t**)hv_realloc(p->ptr, sizeof(student_t*) * maxsize, sizeof(student_t*) * p->maxsize);
    p->maxsize = maxsize;
}
static inline void StudentArray_double_resize(StudentArray* p) {
    StudentArray_resize(p, p->maxsize * 2);
}
static inline void StudentArray_push_back(StudentArray* p, student_t** elem) {
    if (p->size == p->maxsize) {
        StudentArray_double_resize(p);
    }
    p->ptr[p->size] = *elem;
    p->size++;
}
static inline void StudentArray_pop_back(StudentArray* p) {
    ((p->size > 0) ? (void)(0) : __assert_fail("p->size > 0", "/data/hb/libhv/examples/array_test.c", 13, __extension__ __PRETTY_FUNCTION__));
    p->size--;
}
static inline void StudentArray_add(StudentArray* p, student_t** elem, int pos) {
    if (pos < 0) {
        pos += p->size;
    }
    ((pos >= 0 && pos <= p->size) ? (void)(0)
                                  : __assert_fail("pos >= 0 && pos <= p->size", "/data/hb/libhv/examples/array_test.c", 13, __extension__ __PRETTY_FUNCTION__));
    if (p->size == p->maxsize) {
        StudentArray_double_resize(p);
    }
    if (pos < p->size) {
        memmove(p->ptr + pos + 1, p->ptr + pos, sizeof(student_t*) * (p->size - pos));
    }
    p->ptr[pos] = *elem;
    p->size++;
}
static inline void StudentArray_del(StudentArray* p, int pos) {
    if (pos < 0) {
        pos += p->size;
    }
    ((pos >= 0 && pos < p->size) ? (void)(0)
                                 : __assert_fail("pos >= 0 && pos < p->size", "/data/hb/libhv/examples/array_test.c", 13, __extension__ __PRETTY_FUNCTION__));
    p->size--;
    if (pos < p->size) {
        memmove(p->ptr + pos, p->ptr + pos + 1, sizeof(student_t*) * (p->size - pos));
    }
}
static inline void StudentArray_del_nomove(StudentArray* p, int pos) {
    if (pos < 0) {
        pos += p->size;
    }
    ((pos >= 0 && pos < p->size) ? (void)(0)
                                 : __assert_fail("pos >= 0 && pos < p->size", "/data/hb/libhv/examples/array_test.c", 13, __extension__ __PRETTY_FUNCTION__));
    p->size--;
    if (pos < p->size) {
        p->ptr[pos] = p->ptr[p->size];
    }
}
static inline void StudentArray_swap(StudentArray* p, int pos1, int pos2) {
    if (pos1 < 0) {
        pos1 += p->size;
    }
    if (pos2 < 0) {
        pos2 += p->size;
    }
    student_t* tmp = p->ptr[pos1];
    p->ptr[pos1] = p->ptr[pos2];
    p->ptr[pos2] = tmp;
}
#endif

// 创建新的学生
student_t* create_student(const char* name, int age, int high) {
    student_t* student = (student_t*)malloc(sizeof(student_t));
    strncpy(student->name, name, 9);
    student->name[9] = '\0';
    student->age = age;
    student->high = high;
    return student;
}

// 打印学生信息
void print_student(student_t* student) {
    printf("Name: %s, Age: %d, Height: %d\n", student->name, student->age, student->high);
}

int main() {
    StudentArray student_array;

    // 初始化数组
    StudentArray_init(&student_array, ARRAY_INIT_SIZE);

    // 添加学生
    student_t* s1 = create_student("Alice", 20, 165);
    student_t* s2 = create_student("Bob", 22, 180);
    student_t* s3 = create_student("Charlie", 21, 175);

    StudentArray_push_back(&student_array, &s1);
    StudentArray_push_back(&student_array, &s2);
    StudentArray_push_back(&student_array, &s3);

    // 打印数组大小
    printf("Number of students: %d\n", StudentArray_size(&student_array));

    // 访问和打印学生信息
    printf("First student: ");
    print_student(*StudentArray_front(&student_array));

    printf("Last student: ");
    print_student(*StudentArray_back(&student_array));

    printf("Second student: ");
    print_student(*StudentArray_at(&student_array, 1));

    // 添加新学生到特定位置
    student_t* new_student = create_student("David", 19, 170);
    StudentArray_add(&student_array, &new_student, 1);

    // 删除学生
    StudentArray_del(&student_array, 0);

    // 交换学生
    StudentArray_swap(&student_array, 0, 1);

    // 打印所有学生
    printf("\nAll students:\n");
    for (int i = 0; i < StudentArray_size(&student_array); ++i) {
        print_student(*StudentArray_at(&student_array, i));
    }

    // 清空数组并释放内存
    for (int i = 0; i < StudentArray_size(&student_array); ++i) {
        free(*StudentArray_at(&student_array, i));
    }
    StudentArray_clear(&student_array);

    // 检查数组是否为空
    if (StudentArray_empty(&student_array)) {
        printf("\nStudent array is now empty\n");
    }

    // 清理数组
    StudentArray_cleanup(&student_array);

    return 0;
}